﻿using System;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using QQZiFramework.Membership;
using Microsoft.AspNetCore.Mvc.Controllers;

namespace QQZiFramework.Mvc
{
    public enum WeixinAuthorizeState { Default = 0, Enable = 1, Disable = 2 }


    public class LoginCheckFilterAttribute : ActionFilterAttribute
    {
        public LoginCheckFilterAttribute()
        {

        }

        //表示是否检查登录
        public bool IsCheck { get; set; }


        /// <summary>
        /// 是否供外部对接的接口，是的话异常时会以ApiJsonMessage格式输出
        /// </summary>
        public bool IsApiAction { get; set; }
        /// <summary>
        /// 执行模块名称，Action的中文名，用来记录日志
        /// </summary>
        public string Alias { get; set; }
        /// <summary>
        /// 权限验证方式，fromUrl，FromRequest
        /// fromUrl：访问地址，比如Home/Index会映射到Home-Index权限
        /// FromRequest：从参数获取 Request["permission"]
        /// null则不验证
        /// </summary>
        public string CheckPermission { get; set; }

        /// <summary>
        /// 验证地址MD5签名，防串改
        /// </summary>
        /// <value></value>
        public bool CheckUrlMD5 { get; set; }

        /// <summary>
        /// 不校验对应的登录平台是否一定要有Values，比如登录商家是否要求一定有商家记录（商家账号是否开通）
        /// </summary>

        public bool RequireValues { get; set; }

        public static string LoginPage = "/Home/Login";


        /// <summary>
        /// 不要记录提交到Action的信息（客户端提交上来的参数等）
        /// </summary>
        public bool DoNotLogRequest { get; set; }

        /// <summary>
        /// 是否启用微信登录，默认使用WEIXIN_AUTHORIZE
        /// </summary>
        public WeixinAuthorizeState WeixinAuthorize;

        //是否需要忽略控制器的Filter（Action上有定义过滤器的，这里不执行控制器的过滤器）
        bool IgonreControllerFilter(FilterContext filterContext)
        {
            LoginCheckFilterAttribute after = null;
            int currentFilterIndex = -1;
            for (int i = 0; i < filterContext.Filters.Count; i++)
            {
                if (filterContext.Filters[i] is LoginCheckFilterAttribute)
                {
                    if (filterContext.Filters[i] == this)
                    {
                        currentFilterIndex = i;
                    }
                    else if (currentFilterIndex > -1)
                    {
                        after = filterContext.Filters[i] as LoginCheckFilterAttribute;
                    }
                }
            }
            if (after != null) return true;
            else return false;
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (IgonreControllerFilter(filterContext)) return;
            IQQZiController controller = filterContext.Controller as IQQZiController;
            if (controller == null) throw new Exception(filterContext.Controller.GetType().Name + "需要直接或者间接继承IQQZiController");
            DBContext context = controller.CreateDBContext();
            WebHostMemberShip webMemberShip = (WebHostMemberShip)context.Membership;
            webMemberShip.OnActionExecuted(context, filterContext, Alias);
            context.Close();
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (IgonreControllerFilter(filterContext)) return;
            IQQZiController controller = filterContext.Controller as IQQZiController;
            if (controller == null) throw new Exception(filterContext.Controller.GetType().Name + "需要继承IQQZiControlle");
            DBContext context = controller.CreateDBContext();
            HttpContext httpContext = context.GetHttpContext();
            if (httpContext.Request.Headers["HttpMethod"] == "OPTIONS")
            {
                filterContext.Result = new JsonResult(null);
                return;
            }
            if (filterContext.Controller == null) return;
            WebHostMemberShip webMemberShip = (WebHostMemberShip)context.Membership;
            if (webMemberShip == null) return;

            if (WeixinAuthorize != WeixinAuthorizeState.Disable)
            {
                if (WeixinAuthorize == WeixinAuthorizeState.Default)
                {
                    bool defaultRedict = context.GetSettingValue<bool>("WeiXin:MP:UrlRedictAuthorize", false, true);
                    WeixinAuthorize = defaultRedict ? WeixinAuthorizeState.Enable : WeixinAuthorizeState.Disable;
                }

            }
            if (IsApiAction) context.SetArgument("api-action", true);
            bool checkLogin = IsCheck;
            if (IsCheck)
            {
                //配置里是否有重载(先找ActionName有没有，更找Controller有没有)
                string controllerName = controller.GetType().Name;
                string actionName = ((ControllerActionDescriptor)filterContext.ActionDescriptor).ActionName;
                string configValue = context.GetSettingValue<string>("Modules:Web:LoginCheck:" + controllerName + ":" + actionName, false);
                if (configValue == null) configValue = context.GetSettingValue<string>("Modules:Web:LoginCheck:" + controllerName + ":_Default", false);
                if (configValue != null) checkLogin = Convert.ToBoolean(configValue);
            }

            if (!checkLogin) return;
            BaseUser u = webMemberShip.GetUserFrom(context);
            //记录操作痕迹
            String userAgent = httpContext.Request.Headers["User-Agent"];
            HttpRequest request = httpContext.Request;
            context.SetArgument("LoginCheckFilter", this);
            if (!DoNotLogRequest)
            {
                //requestContent
                webMemberShip.OnActionExecuting(context, filterContext, Alias);

            }
            bool islogin = u != null;

            // if (WeixinAuthorize == WeixinAuthorizeState.Enable)
            // {
            //     Weixin.WxSetting setting = Weixin.WxAccessTokenDriver.GetSetting(context);
            //     //是否微信登录
            //     if (userAgent != null && !WebHostMemberShip.IsAjax(context) && userAgent.IndexOf("MicroMessenger", StringComparison.OrdinalIgnoreCase) > -1)
            //     {
            //         Weixin.OAuthUser weiUser = WebHostMemberShip.GetWeiXinUser(controller);
            //         if (weiUser == null)
            //         {
            //             string url = WebHostMemberShip.GetPathAndQuery(httpContext.Request);
            //             if (url == "" || url == "/") url = "/Home/Index";

            //             string WeiXinAuthPage = "/" + context.OEM.Name + "/WeiXin/WxAuth";
            //             url = WeiXinAuthPage + "?backUrl=" + System.Net.WebUtility.UrlEncode(url);
            //             filterContext.Result = new RedirectResult(url);
            //             return;
            //         }
            //         // else
            //         // {
            //         //     if (!islogin && weiUser.IsRegister)
            //         //     {
            //         //         //自动登录
            //         //         controller.LoginWeiXin(context);
            //         //     }
            //         //     controller.ViewBag.WeiXinUser = weiUser;
            //         // }
            //     }
            //     if (userAgent != null && !WebHostMemberShip.IsAjax(context) && userAgent.IndexOf("AlipayClient", StringComparison.OrdinalIgnoreCase) > -1)
            //     {

            //     }
            // }
        

            if (!islogin)
            {
                throw new NotLoginException();
                // //ajax访问，NotLoginException
                // if (WebHostMemberShip.IsAjax(context)) throw new NotLoginException();
                // //非ajax访问跳转到登录
                // string url = WebHostMemberShip.GetPathAndQuery(httpContext.Request);
                // if (url == "" || url == "/") url = "/Home/Index";
                // if (httpContext.Session != null)
                // {
                //     httpContext.Session.SetString("backurl", url);
                //     context.LogMessage("跳转到登录，backurl：" + url);
                // }
                // filterContext.Result = new RedirectResult(LoginPage);

            }
            TokenInfo tokenInfo = ((WebHostMemberShip)context.Membership).GetTokenInfo(context);
            if (CheckUrlMD5)
            {
                //验证请求是否合法
                string url = webMemberShip.GetUrlForMd5Check((ControllerBase)controller);
                string md5 = httpContext.Request.Query["secret"];
                string timeSpan = httpContext.Request.Query["ts"];
                string md5_2 = Utility.EncryptMD5(url + u.UserId + tokenInfo.AppSecret + timeSpan);
                if (!md5_2.Equals(md5, StringComparison.OrdinalIgnoreCase))
                {
                    throw new NotAlowAccessException();
                }
                long Sticks = Utility.GetIntFromTime(DateTime.Now);
                if (Sticks - Convert.ToSingle(timeSpan) > 600000)
                {
                    //10分钟后，地址过期
                    throw new ClientException("该地址已过期，或者日期与服务器不一致！");
                }
            }

            //验证权限
            if (CheckPermission == null) return;
            if (RequireValues && tokenInfo.PlatfromId == LoginPlatfromId.MerchantAdmin && tokenInfo.Values == null)
            {
                throw new NotMerchantExcepton();
            }
            string permission = CheckPermission.ToLower();

            MembershipBLL bll = context.GetBusiness<MembershipBLL>();
            if (permission == "fromurl")
            {
                permission = httpContext.Request.Path;
                if (permission[0] == '/') permission = permission.Substring(1);
                permission = context.Membership.OnUrlPermission(permission);
                //通过地址查找权限
                Permission p = bll.GetPermissionByMenu(u.UserId, permission, tokenInfo.PlatfromId);
                if (p == null)
                {
                    //如果没有地址，通过权限名再找
                    permission = permission.Replace('/', '-');
                    if (!bll.HasPermisson(u.UserId, permission, tokenInfo.PlatfromId)) throw new ClientException("您没有操作该块的权限" + permission);
                }
                else permission = p.Name;
            }
            else
            {
                if (permission == "fromrequest")
                {
                    permission = controller.GetParamValue("permission", 0, false, true);
                    if (permission.StartsWith("public-")) return;//public开头的不核验权限
                    string ext = context.GetArgument("permission-ext") as string;
                    if (ext != null) permission += ext;//-Save或者-Delete
                    if (string.IsNullOrEmpty(permission)) throw new ClientException("permission不能为空！");
                }
                if (permission != "" && permission != "-")
                {
                    if (!bll.HasPermisson(u.UserId, permission, tokenInfo.PlatfromId)) throw new ClientException("您没有操作该块的权限:" + permission);
                }
            }



        }



    }
}